iT邦幫忙

2025 iThome 鐵人賽

DAY 7
0
自我挑戰組

打造自己的Medium系列 第 7

Day7 Vue基礎篇(下)

  • 分享至 

  • xImage
  •  

今天來介紹比較容易混淆的部分

功能介紹

  1. computed
    使用情境比較接近,需要處理ref做計算,但是希望ref未變動時,不要重新執行。
    雖然有辦法寫getter/setter,來達到傳參數修改計算值的目的,但官方不太建議這麼做
let id = 0
const hideCompleted = ref(false)
const todos = ref([
  { id: id++, text: 'Learn HTML', done: true },
  { id: id++, text: 'Learn JavaScript', done: true },
  { id: id++, text: 'Learn Vue', done: false }
])

const filteredTodos = computed(() => {
  return hideCompleted.value
    ? todos.value.filter((t) => !t.done)
    : todos.value
})

理論上可以像下面直接寫在template裡,若遇到要重複使用的話,可以改成呼叫function來減少冗長的程式碼,但是這些都不像computed有快取功能,不會只在有變動時才執行

{{ hideCompleted.value
    ? todos.value.filter((t) => !t.done)
    : todos.value }}
  1. watchEffect
    跟computed一樣會自動監聽用到的ref,但不會單純回傳計算結果,而是處理其他的變化,也被稱作副作用,如:發送非同步的請求,變更組件等等
const todoId = ref(1)
const data = ref(null)

watchEffect(async () => {
  const response = await fetch(
    `https://jsonplaceholder.typicode.com/todos/${todoId.value}`
  )
  data.value = await response.json()
})
  1. watch
    高可控性版本的watchEffect,需要自己指定監聽的ref,並且可以讀取變化前後的值,執行的方式等。
const todoId = ref(1)
const data = ref(null)

watch(
  todoId,
  async () => {
    const response = await fetch(
      `https://jsonplaceholder.typicode.com/todos/${todoId.value}`
    )
    data.value = await response.json()
  },
  { immediate: true }
)

組件溝通

將資料參數傳入子組件prop

  1. 在子組件定義參數
//ChildComp.vue
<script setup>
const props = defineProps({
  msg: String
})
</script>

<template>
  <h2>{{ msg || 'No props passed yet' }}</h2>
</template>

2.在父組件使用,並傳入參數

//ParentComp.vue
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const greeting = ref('Hello from parent')
</script>
<template>
 // 使用:<prop name>指定傳入參數
  <ChildComp :msg="greeting" />
</template>

將事件通知到父組件emit

  1. 在子組件定義事件
//ChildComp.vue
<script setup>
const emit = defineEmits(['response'])

emit('response', 'hello from child')
</script>

<template>
  <h2>Child component</h2>
</template>

2.在父組件接收通知

//ParentComp.vue
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const childMsg = ref('No child msg yet')
</script>

<template>
  <ChildComp @response="(msg) => childMsg = msg" />
  <p>{{ childMsg }}</p>
</template>

使用prop + emit就是俗稱的雙向綁定

將內容插入子組件slot

這裡跟prop不同的是,slot其實是在父組件範圍處理的,所以不需要emit。

slot還有更多進階用法,可以參考這篇

  1. 在子組件定義參數
//ChildComp.vue
<template>
  <slot>Fallback content</slot>
</template>

2.在父組件取代掉<slot></slot>

//ParentComp.vue
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'

const msg = ref('from parent')
</script>

<template>
  <ChildComp>Message: {{ msg }}</ChildComp>
</template>

生命週期

在不考慮options API的情況下,有以下幾個階段:

  1. 初始化Setup
    執行初始化邏輯,如狀態定義、函數定義等
  2. 掛載 Mount
    • 前: 在 DOM 尚未插入之前
    • 後: 元件第一次渲染完畢,適合請求資料、操作 DOM
  3. 更新 Update
    • 前: 在狀態變更觸發 DOM 更新前執行
    • 後: 每次更新後會觸發

    大多數常見的網頁互動與畫面變化,通常都發生在這個階段

  4. 卸載 Unmount
    • 前: 在元件被移除前執行
    • 後: 最後一個操作階段

對照

框架 Vue React
計算 computed useMemo
副作用 watch, watchEffect useEffect

參考資料

  1. Computed Properties
  2. 不只懂 Vue 語法:試解釋 computed、watch 與 methods 的差異?
  3. Watchers
  4. Lifecycle Hooks

作者的哈拉

進入倦怠期/images/emoticon/emoticon70.gif


上一篇
Day6 Vue基礎篇(上)
下一篇
Day8 Vue + Typescript
系列文
打造自己的Medium30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言